from app_package import AppPackage
import time as t
from selenium.common.exceptions import NoSuchElementException
from appium.webdriver.common.mobileby import MobileBy
from personal_exceptions import HideKeyboardException
from common.user_data import project_name as p_name

# 一些定位元素方法的缩写，以便缩减代码长度
IOS = MobileBy.IOS_PREDICATE
XPATH = MobileBy.XPATH


class Page(AppPackage):  # 页面对象，所有页面继承此类，集成部分页面中常用方法

    def __init__(self, page=None):
        if page:
            self.driver = page.driver
        else:
            super(Page, self).__init__()

    def find_element(self, *args, times=10):
        """查找元素 (使用循环判断增加健壮性)"""
        for i in range(times):
            try:
                self.driver.find_element(*args)
            except NoSuchElementException:
                t.sleep(1)
                continue
            else:
                return self.driver.find_element(*args)
        # return self.driver.find_element(*args)

    def find_elements(self, *args, times=5):
        """查找多个元素"""
        ele_list = self.driver.find_elements(*args)
        for i in range(times):
            if ele_list:
                return ele_list
            else:
                t.sleep(0.5)
                ele_list = self.driver.find_elements(*args)
        return ele_list

    def find_button(self, string, contains_flag=0, attr='label', times=10):
        return self.find_element(IOS, "type == 'XCUIElementTypeButton' AND %s %s '%s'" %
                                 (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_buttons(self, string, contains_flag=0, attr='label', times=10):
        return self.find_elements(IOS, "type == 'XCUIElementTypeButton' AND %s %s '%s'" %
                                  (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_static_text(self, string, contains_flag=0, attr='label', times=10):
        return self.find_element(IOS, "type == 'XCUIElementTypeStaticText' AND %s %s '%s'" %
                                 (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_static_texts(self, string, contains_flag=0, attr='label', times=10):
        return self.find_elements(IOS, "type == 'XCUIElementTypeStaticText' AND %s %s '%s'" %
                                  (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_text_view(self, string, contains_flag=0, attr='label', times=10):
        return self.find_element(IOS, "type == 'XCUIElementTypeTextView' AND %s %s '%s'" %
                                 (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_image(self, string, contains_flag=0, attr='label', times=10):
        return self.find_element(IOS, "type == 'XCUIElementTypeImage' AND %s %s '%s'" %
                                 (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_images(self, string, contains_flag=0, attr='label', times=10):
        return self.find_elements(IOS, "type == 'XCUIElementTypeImage' AND %s %s '%s'" %
                                  (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_text_field(self, string, contains_flag=0, attr='label', times=10):
        return self.find_element(IOS, "type == 'XCUIElementTypeTextField' AND %s %s '%s'" %
                                 (attr, 'CONTAINS' if contains_flag else '==', string), times=times)

    def find_xpath(self, string, times=10):
        return self.find_element(XPATH, string, times=times)

    def find_xpaths(self, string, times=10):
        return self.find_elements(XPATH, string, times=times)

    def get_driver(self):  # 返回对象中的driver
        return self.driver

    def tap(self, x, y):
        """点击坐标点的方法
        execute_script: scroll, swipe, pinch, doubleTap,
                        twoFingerTap, touchAndHold, tap,
                        dragFromToForDuration
        """
        self.driver.execute_script("mobile: tap", {"tapCount": 1,
                                                   "touchCount": 1,
                                                   "duration": 0.5,
                                                   "x": x,
                                                   "y": y})

    def touch_and_hold(self, ele, time):
        self.driver.execute_script("mobile: touchAndHold", {"element": ele,
                                                            "duration": time})

    def swipe(self, x1, y1, x2, y2, duration=0.1):  # 滑动方法(iOS特有)
        self.driver.execute_script("mobile:dragFromToForDuration", {"duration": duration,
                                                                    "element": None,
                                                                    "fromX": x1,
                                                                    "fromY": y1,
                                                                    "toX": x2,
                                                                    "toY": y2})

    def swipe_dr(self, direction='up'):  # 上下左右滑动的方法
        screen_size = self.driver.get_window_size()
        width, height = screen_size['width'], screen_size['height']
        if direction.lower() == 'up':
            self.swipe(width/2, height/4*3, width/2, height/4)
        elif direction.lower() == 'down':
            self.swipe(width/2, height/4, width/2, height/4*3)
        elif direction.lower() == 'right':
            self.swipe(width/4, height/2, width/4*3, height/2)
        elif direction.lower() == 'left':
            self.swipe(width/4*3, height/2, width/4, height/2)

    def hide_keyboard(self):  # 隐藏键盘
        try:
            self.driver.find_element(IOS, 'type == "XCUIElementTypeButton" AND label == "完成"').click()
        except NoSuchElementException:
            raise HideKeyboardException()
    def Hide_Key(self):
        try:
            self.driver.find_element(IOS, 'type == "XCUIElementTypeButton" AND label == "Done"').click()
        except NoSuchElementException:
           raise HideKeyboardException()

    def get_frame_center_and_swipe(self, ele_location, duration=0.1, flag=1):  # 拖动选择框
        ele = self.find_element(*ele_location, times=3)
        location, size = ele.location, ele.size
        center_x, center_y = location['x'] + size['width']//2, location['y'] + size['height']//2
        if flag:
            self.swipe(center_x, center_y, center_x, location['y'], duration)
        else:
            self.swipe(center_x, center_y, center_x, location['y']+size['height'], duration)

    def get_frame_center_and_click_limit(self, ele_location, limit=0):  # 获取元素的中心点坐标并点击此坐标
        ele_list = self.driver.find_elements(*ele_location)
        for ele in ele_list:
            location, size = ele.location, ele.size
            center_x, center_y = location['x'] + size['width']//2, location['y'] + size['height']//2
            if center_y >= limit:
                print("(%d, %d)" % (center_x, center_y))
                self.tap(center_x, center_y)
                break

    def get_frame_center_and_click(self, ele, flag=1):
        """获取元素的中心点坐标并点击此坐标
        flag控制传参类型，flag=1时，ele可传入元素定位方法；flag=0时，ele可直接传入元素
        """
        if flag:
            ele = self.driver.find_element(*ele)
        location, size = ele.location, ele.size
        center_x, center_y = location['x'] + size['width'] // 2, location['y'] + size['height'] // 2
        print("(%d, %d)" % (center_x, center_y))
        self.tap(center_x, center_y)

    def return_enter_project(self, project_name=p_name):
            # self.find_element(*self.project_btn).click()
            t.sleep(4)

            for i in range(5):
                try:
                    ele = self.find_static_text(string=project_name, contains_flag=1)
                    ele.click()
                    # self.find_static_text(string=project_name, contains_flag=1).click()
                except NoSuchElementException:
                    # self.swipe_dr('up')
                    self.swipe(40, 470, 40, 440)
                    t.sleep(2)
                    # self.find_static_text(string=project_name, contains_flag=1, times=5).click()
                    continue
                else:
                    break
            t.sleep(2)
